package com.apestech.api.condition.Step;

import com.apestech.framework.db.SqlSession;
import com.apestech.framework.file.callback.VarOperCallBack;
import com.apestech.framework.json.JSONObject;
import com.apestech.framework.util.MathUtil;
import com.apestech.framework.util.callback.SpiltStrCallback;
import com.apestech.framework.xml.condition.modul.ConditionStrategy;

import java.math.BigDecimal;
import java.util.ArrayList;

public abstract class StepPubField extends StepUtil implements StepLifeCycleInter{
    private SqlSession session;
    private ConditionStrategy.Step step;
    private JSONObject input=new JSONObject();
    private JSONObject mustInput=new JSONObject();
    private JSONObject out=new JSONObject();

    private ConditionStrategy conditionStrategy;
    private JSONObject resultMap;

    public StepPubField(ConditionStrategy.Step step, SqlSession session) throws Exception {
        this.step=step;
        this.session=session;
        mustInput=getInputfields(step.getInputfields());
        step.setMustInput(mustInput.getKeyStr());
    }

    public JSONObject getOut() {
        return out;
    }

    public void setOut(JSONObject out) {
        this.out = out;
    }

    @Override
    public void setConditionStrategyVar(ConditionStrategy conditionStrategy, JSONObject resultMap) {
        this.conditionStrategy = conditionStrategy;
        this.resultMap = resultMap;
    }

    @Override
    public JSONObject getResultMap() {
        return resultMap;
    }

    @Override
    public JSONObject getMinInput() throws Exception {
        return mustInput;
    }

    @Override
    public void setInput(JSONObject input) throws Exception {
        if(input!=null){
            this.input=getInputParamFromStr(input, step);
        } else {
            this.input=null;
        }
    }

    @Override
    public void exec() throws Exception {
        if("save".equals(step.getType())) {
            if(step.isIstrans()){
                session.saveTable_T(step.getTabname(), input);
            } else {
                session.getForUpdate().saveTable(step.getTabname(), input);
            }
        } else if("insert".equals(step.getType())){
            if(step.isIstrans()){
                session.insertTable_T(step.getTabname(), input);
            } else {
                session.getForUpdate().insertTable(step.getTabname(), input);
            }
        } else if("update".equals(step.getType())){
            if(step.isIstrans()){
                if(step.getSql()!=null){
                    session.update_T(step.getSql(), input);
                } else {
                    session.updateTable_T(step.getTabname(), input);
                }
            } else {
                if(step.getSql()!=null){
                    session.getForUpdate().update(step.getSql(), input);
                } else {
                    session.getForUpdate().updateTable(step.getTabname(), input);
                }
            }
        } else if("delete".equals(step.getType())){
            if(step.isIstrans()){
                session.deleteTable_T(step.getTabname(), input);
            } else {
                session.getForUpdate().deleteTable(step.getTabname(), input);
            }
        }
    }

    @Override
    public void setOutput() throws Exception {
        int outSize=step.getOutputs().size();
        if(resultMap==null){
            resultMap=new JSONObject();
        }
        if(step.getOutputfields()==null && outSize==0){
            out.putAll(step.getResultMap());
        }
        else if(step.getOutputfields()!=null){
            setOutputParamFromStr(step.getOutputfields(), step.getResultMap(), out); //resultMap
        }
        else if(outSize>0){
            setOutputParamFromField(step.getOutputs(), step.getResultMap(), out, conditionStrategy);  //resultMap
        }
        if(step.getExpress()!=null){
            String exp=step.getExpress();
            //#{OUT_PORTION}
            //OUT_PORTION="PORTION_#{id}"
            String k=getRealKey(exp, input, new VarOperCallBack(){
                @Override
                public String getString(String instr) throws Exception {
                    return getRealKey(input.getString(instr), input);
                }
            });
            if(k!=null){
                exp=k;
            }
            Object rvalue=doExpression(exp, out, resultMap, input);
            if(rvalue instanceof BigDecimal){
                rvalue= MathUtil.round(castToDouble(rvalue), 4);
            }
            out.put(step.getId(), rvalue);  //step.getResultMap()
        }
        String SYS_NO_CHECK=input.getString("SYS_NO_CHECK");
        if(SYS_NO_CHECK!=null){
            execSplitStr(SYS_NO_CHECK, ",", new SpiltStrCallback() {
                @Override
                public void exec(String id) throws Exception {
                    if(input.get(id)==null && out.get(id)==null &&  step.getResultMap()!=null &&  step.getResultMap().get(id)!=null){
                        out.put(id, step.getResultMap().get(id));
                    }
                }
            });
        }
        if(step.isIsremove()){
            out.remove(step.getId());
            return;
        }

        if(step.getValue()!=null){
            out.put(step.getId(), step.getValue());
        }
        if(step.getResult()!=null){
            //out.put(step.getId(), doExpression(step.getResult(), out, step.getResultMap()));
            if(resultMap.get(step.getResult())!=null){
                out.put(step.getId(), resultMap.get(step.getResult()));
            } else if(out.get(step.getResult())!=null){
                out.put(step.getId(), out.get(step.getResult()));
            } else if(input.get(step.getResult())!=null){
                out.put(step.getId(), input.get(step.getResult()));
            }
            //out.put(step.getId(), doExpression(step.getResult(), out, step.getResultMap()));
        }
        if(step.getNullValue()!=null){
            if(resultMap.get(step.getId())==null && input.get(step.getId())==null){
                out.put(step.getId(), step.getNullValue());
            }
        }
        if(out.size()==0){
            JSONObject other=step.getOther();
            ArrayList<String> klist=other.getKeylist();
            int len=klist.size();
            for(int i=0; i<len; i++){
                String k=klist.get(i);
                if(k.indexOf("default")>=0){
                    Double value=castToDouble(k.substring(k.indexOf("_")+1, k.length()));
                    execSplitStr(other.getString(k), ",", new SpiltStrCallback() {
                        @Override
                        public void exec(String id) throws Exception {
                            out.put(id, value);
                        }
                    });
                }
            }
        } else {
            if("condition".equals(step.getType()) && step.getResultMap()!=null){
                out.put("C_ID", step.getResultMap().getString("C_ID"));
                out.put("DIMENSION_ID", step.getResultMap().getString("DIMENSION_ID"));
                out.put("RESULT_DATA", step.getResultMap().getString("RESULT_DATA"));
            }
        }
        resultMap.putAll(out);
    }

    @Override
    public String showMinInput() throws Exception {
        return null;
    }

    public SqlSession getSession() {
        return session;
    }

    public ConditionStrategy.Step getStep() {
        return step;
    }

    public JSONObject getInput() {
        return input;
    }

    public void setResultMap(JSONObject resultMap) {
        this.resultMap = resultMap;
    }
}
